package com.alien.admin.modules.basic.service.impl;

import com.alien.admin.exception.BadRequestException;
import com.alien.admin.modules.deploy.domain.DpJenkinsInstance;
import com.alien.admin.modules.basic.service.JenkinsService;
import com.alien.admin.utils.DeployConstant;
import com.alien.admin.utils.JsonUtil;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.Base64;

/**
 * @description: jenkins服务实现
 * @author: zhouseyi
 * @date: 2021/9/24 9:30
 * @version: 1.0
 */
@Service
public class JenkinsServiceImpl implements JenkinsService {

    final RestTemplate restTemplate;

    public JenkinsServiceImpl() {
        SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
        factory.setConnectTimeout(600000);
        factory.setReadTimeout(15000);
        restTemplate = new RestTemplate(factory);
    }

    @Value("${deployServer.postUrl}")
    String postUrl = "";

    private BaseResponseEntity post(JenkinsPostEntity jenkinsPostEntity, String methodUrl) {
        HttpEntity<String> request = buildPostEntity(jenkinsPostEntity);
        String getJobUrl = postUrl + "/jenkins/" + methodUrl;
        BaseResponseEntity jenkinsResponseEntity = restTemplate.postForObject(getJobUrl, request, BaseResponseEntity.class);
        String status = jenkinsResponseEntity.getStatus();
        if("error".equals(status)) {
            throw new BadRequestException(jenkinsResponseEntity.getError());
        }
        return jenkinsResponseEntity;
    }

    BaseResponseEntity postForResponse(DpJenkinsInstance instance, String methodUrl, String jobName) {
        JenkinsPostEntity jenkinsPostEntity = new JenkinsPostEntity(instance);
        jenkinsPostEntity.setJobName(jobName);

        return post(jenkinsPostEntity, methodUrl);
    }

    BaseResponseEntity postForResponse(DpJenkinsInstance instance, String methodUrl, String jobName, String params) {
        JenkinsPostEntity jenkinsPostEntity = new JenkinsPostEntity(instance);
        jenkinsPostEntity.setJobName(jobName);
        jenkinsPostEntity.setParams(params);

        return post(jenkinsPostEntity, methodUrl);
    }

    BaseResponseEntity postForResponse(DpJenkinsInstance instance, String methodUrl, String jobName, Long queueId) {
        JenkinsPostEntity jenkinsPostEntity = new JenkinsPostEntity(instance);
        jenkinsPostEntity.setJobName(jobName);
        jenkinsPostEntity.setQueueId(queueId);

        return post(jenkinsPostEntity, methodUrl);
    }

    private HttpEntity<String> buildPostEntity(JenkinsPostEntity jenkinsPostEntity) {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);
        String tokenPostVOStr = JsonUtil.object2Json(jenkinsPostEntity);
        HttpEntity<String> request = new HttpEntity<String>(tokenPostVOStr, httpHeaders);
        return request;
    }

    @Override
    public boolean hasJob(DpJenkinsInstance instance, String jobName) {
        BaseResponseEntity jenkinsResponseEntity = postForResponse(instance, "getJenkinsJob", jobName);
        return (Boolean)jenkinsResponseEntity.getData();
    }

    @Override
    public boolean getLastBuild(DpJenkinsInstance instance, String jobName) {
        BaseResponseEntity jenkinsResponseEntity = postForResponse(instance, "getJenkinsJobLastBuild", jobName);
        Object data = jenkinsResponseEntity.getData();
        if(data == null) {
            return false;
        }
        return (Boolean)data;
    }

    @Override
    public Integer buildJob(DpJenkinsInstance instance, String jobName, String params) {
        BaseResponseEntity jenkinsResponseEntity = postForResponse(instance, "buildJenkinsJob", jobName, params);
        Object data = jenkinsResponseEntity.getData();
        if(data == null || !(data instanceof Integer)) {
            return -1;
        }
        return (Integer)data;
    }

    @Override
    public Integer getBuildResult(DpJenkinsInstance instance, String jobName, Long queueId) {
        BaseResponseEntity jenkinsResponseEntity = postForResponse(instance, "getJenkinsBuildResult", jobName, queueId);
        Object data = jenkinsResponseEntity.getData();
        // FAILURE SUCCESS
        if(data == null) {
            return DeployConstant.DEPLOY_STATUS_RUNNING;
        }
        String dataStr = String.valueOf(data);
        if(dataStr.equals("SUCCESS")) {
            return DeployConstant.DEPLOY_STATUS_SUCCESS;
        } else if(dataStr.equals("FAILURE")) {
            return DeployConstant.DEPLOY_STATUS_FAILED;
        } else if(dataStr.equals("ABORTED")) {
            return DeployConstant.DEPLOY_STATUS_FAILED;
        }
        return DeployConstant.DEPLOY_STATUS_RUNNING;
    }

    @Override
    public String getBuildLog(DpJenkinsInstance instance, String jobName, Long queueId) {
        BaseResponseEntity jenkinsResponseEntity = postForResponse(instance, "getJenkinsBuildLog", jobName, queueId);
        Object data = jenkinsResponseEntity.getData();
        if(data == null) {
            return "";
        }
        return String.valueOf(data);
    }

    @Override
    public boolean createJob(DpJenkinsInstance instance, String jobName, String jobContent) {
        // 进行base64编码
        String encodeJobContent;
        try {
            encodeJobContent = Base64.getEncoder().encodeToString(jobContent.getBytes("utf-8"));
            JenkinsPostEntity jenkinsPostEntity = new JenkinsPostEntity(instance);
            jenkinsPostEntity.setJobName(jobName);
            jenkinsPostEntity.setJobContent(encodeJobContent);

            post(jenkinsPostEntity, "createJenkinsJob");

        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

        return true;
    }

    @Data
    private static class JenkinsPostEntity {

        public JenkinsPostEntity(DpJenkinsInstance instance) {
            this.url = instance.getUrl();
            this.token = instance.getToken();
            this.userName = instance.getUsername();
        }
        private String url;
        private String token;
        private String userName;

        private String jobName;
        private Long queueId;
        private String params;
        private String jobContent;
    }
}
